Go语言基础:切片slice的声明及使用

您所在的位置:网站首页 go 初始化切片 Go语言基础:切片slice的声明及使用

Go语言基础:切片slice的声明及使用

2024-01-18 18:26| 来源: 网络整理| 查看: 265

前言

大家好,我是沐风晓月,本文go语言入门-掌握go语言函数收录于《go语言学习专栏》专栏,此专栏带你从零开始学习go语言,持续更新中,欢迎点赞收藏。

🏠个人主页:我是沐风晓月 🧑个人简介:大家好,我是沐风晓月,双一流院校计算机专业,阿里云博客专家 😉😉 💕 座右铭:先努力成长自己,再帮助更多的人,一起加油进步 🍺🍺🍺💕欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信

文章目录 前言一. 切片的定义1.1 切片的定义和特点1.2 切片的结构 二. 切片的声明和初始化2.1 声明切片2.2 初始化切片 三. 为切片元素赋值3.1 添加元素 append() 方法3.2 切片拷贝 copy()方法3.3 从切片中删除元素 总结

在这里插入图片描述

一. 切片的定义 1.1 切片的定义和特点

Go语言中的切片,是一种动态数组,它是对数组的引用,切片本身并不存储任何数据,它只是描述了数组中的一段。

切片有如下几个特点:

与数组相⽐,切⽚的⻓度是不固定的,可以追加元素,在追加时可能使切⽚的容量增⼤。切⽚本身没有任何数据,它们只是对现有数组的引⽤。切⽚与数组相⽐,不需要设定⻓度,在[]中不⽤设定值,相对来说⽐较⾃由。切片是引用类型,默认值为nill切片的索引也是从零开始切片的遍历方式与数组相同

从概念上⾯来说slice像⼀个结构体,这个结构体包含了三个元素:

1)指针,指向数组中slice指定的开始位置; 2)长度,即slice的当前⻓度; 3)容量,也就是slice所容纳的最大元素个数。

1.2 切片的结构

切片是一种数据类型,这种数据类型便于使用和管理数据集合。

首先我们需要明白切片的结构。slice在Go的运行时库中就是一个C语言动态数组的实现:

type slice struct { ptr *array //底层存储数组 len int //当前存储了多少个元素 cap int //底层数组可以存储多少个元素(从ptr指向的位置开始) }

这个结构有3个字段,第一个字段表示array的指针,就是真实数据的指针(这个一定要注意),第二个是表示slice的长度,第三个是表示slice的容量,特别需要注意的是:

1.slice的长度和容量都不是指针 2.切片操作并不复制切片指向的元素。它创建一个新的切片并复用原来切片的底层数组。

切片操作并不复制切片指向的元素。它创建一个新的切片并复用原来切片的底层数组。 使得切片操作和数组索引一样高效。因此,通过一个新切片修改元素会影响到原始切片的对应元素。

切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。

在这里插入图片描述 这 3 个字段分别是指向底层数组的指针、切片访问的元素的个数(即长度)和切片允许增长到的元素个数(即容量)。

二. 切片的声明和初始化 2.1 声明切片

1. 声明一个未指定长度的数组来定义切片

语法:

var slicename []type slicename : 表示变量名

需要注意的是: 该声明⽅式中未初始化的切⽚为空切⽚。该切⽚默认为 nil,⻓度为 0。

package main import "fmt" func main() { var a []string //声明一个字符串切片 var b = []int{} // 声明一个整数切片并初始化 fmt.Println(a, b, a == nil) // 执行结果 [] [] true }

2. 使用make()的方式声明切片

语法:

var slice1 []type = make([]type, len, cap) //type 表示切片的元素类型 //len 表示切片中元素的数量 //cap 表示切片的最大容量 可进行缩写: - var slice1 []type = make([]type, len) - 可以简写为: slice1 := make([]type, len)

案例一:使用make直接定义切片

package main import "fmt" func main() { var mufeng2 []int = make([]int, 5, 7) var mufeng2 []int = make([]int, 5) // 缩写 fmt.Println(mufeng2) } //执行结果: [0 0 0 0 0]

案例二:使用make定义并获相应的len,cap

package main import "fmt" func main() { var mufeng = make([]int, 1, 6) fmt.Println(mufeng) fmt.Println(len(mufeng), cap(mufeng), mufeng) fmt.Printf("len=%d cap=%d,slice=%v\n", len(mufeng), cap(mufeng), mufeng) }

执行结果:

[0] 1 6 [0] len=1 cap=6,slice=[0]

len : 表示长度 cap: 表示容量

容量可以省略不写,若不写默认与len相同。

使用make() 定义的时候,系统会初始化为0,而不是nil。之所以 不是nil ,是因为make 函数为其 分配了内存空间。

2.2 初始化切片

1. 直接初始化切片

package main import "fmt" func main() { mufeng := []int{1, 2, 3} //由系统自动创建底层数组 fmt.Println(mufeng) } //执行结果: [1 2 3]

2. 基于数组来截取初始化切片

package main import "fmt" func main() { //定义数组: mufeng := [5]int{1, 2, 3, 4, 5} //定义切片: s := mufeng[:] //切片中包含数组的所有数据 s1 := mufeng[2:4] s2 := mufeng[1:] //从下标1到最后 s3 := mufeng[:3]// 从最开始到下标为3-1 fmt.Println(mufeng, s, s1, s2, s3) //执行结果: }

执行结果:

[1 2 3 4 5] [1 2 3 4 5] [3 4] [2 3 4 5] [1 2 3]

代码详解:

定义数组: mufeng := [5]int{1, 2, 3, 4, 5}

切片中包含数组中所有的数据: s := mufeng[:] s := mufeng[startIndex:endIndex]表示从startIndex 到endIndex : s1 := mufeng[2:4]

这里的[]是一个前闭后开区间

比如这这个例子中,这里的startIndex就是2,endIndex就是4, 所以s1 := mufeng[2:4] 就是获取下标为2到4的值,结果就是[3, 4], 但这里不包含下标4

[2:4] == 21, 2, 3}...) //追加一个切片 fmt.Println(mufeng, mufeng1, mufeng2) }

输出结果:

[1] [1 2 3 4] [1 1 2 3]

这里需要注意: append() 在为切片去动态添加元素的时候,如果空间不足以容纳足够多的元素的时候,切片就会进行扩容。切片在扩容时,容量的扩展规律是按容量的 2 倍数进行扩充,例如 1、2、4、8、16等倍数扩容。

package main import "fmt" func main() { var mufeng []int for num := 0; num mufeng1 := []int{1, 2, 3, 4, 5} mufeng2 := []int{5, 6, 7} a := copy(mufeng1, mufeng2) b := copy(mufeng2, mufeng1) fmt.Println(a, b) //这里返回的是复制的总元素个数 3,3 fmt.Println(mufeng1, mufeng2) //[5 6 7 4 5] [5 6 7] }

复制的流程: mufeng1 复制到mufeng2 :

mufeng2前三个元素{5,6,7} 占位,只需要把mufeng1的{4,5}复制过来即可,也就是:{5,6,7,4,5}

3.3 从切片中删除元素

Go语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素,根据要删除元素的位置有三种情况,分别是从开头位置删除、从中间位置删除和从尾部删除,其中删除切片尾部的元素速度最快。

从开头位置删除 package main import "fmt" func main() { mufeng1 := []int{1, 2, 3, 4, 5} mufeng1 = mufeng1[1:] //删除开头的一个元素 fmt.Println(mufeng1) //[2 3 4 5] mufeng1 = mufeng1[3:] //删除开头的三个元素 fmt.Println(mufeng1) //【5】 } 删除第二个元素 package main import "fmt" func main() { mufeng1 := []int{1, 2, 3, 4, 5} fmt.Println(mufeng1) mufeng1 = append(mufeng1[:1], mufeng1[1+1:]...) fmt.Println(mufeng1) }

执行结果:

[1 2 3 4 5] [1 3 4 5] 截取法

这里利用对 slice 的截取删除指定元素。注意删除时,后面的元素会前移,所以下标 i 应该左移一位。

上面的第二种方法也是这种方法,其实需要自己指定要删除的下标,接下来我们用for循环实现:

import "fmt" func DeleteSlice(a []int, elem int) []int { for i := 0; i a = append(a[:i], a[i+1:]...) i-- } } return a } func main() { x := DeleteSlice([]int{1, 2, 3, 4, 5}, 2) fmt.Println(x) //[1 3 4 5] }

这种方法修改了原来的切片: 切片是一个有三个字段的结构体,分别是: 地址,长度和容量, 这还总方法改变的是地址和长度,但是容量没有变:

package main import "fmt" func DeleteSlice(a []int, elem int) []int { for i := 0; i a = append(a[:i], a[i+1:]...) i-- } } return a } func main() { p := []int{1, 2, 3, 4, 5} fmt.Println(p, len(p), cap(p)) fmt.Printf("address of p %p", &p) x := DeleteSlice(p, 2) fmt.Println(x) //[1 3 4 5] fmt.Println(len(x), cap(x)) fmt.Printf("address of x %p", &x) }

执行结果:

C:\Users\Administrator\AppData\Local\Temp\GoLand\___go_build_test_hello_go.exe [1 2 3 4 5] 5 5 address of p 0xc000008078 [1 3 4 5] 4 5 address of x 0xc0000080a8 总结

切片这边比较难,建议每隔一段时间就回来复习。

💕 好啦,这就是今天要分享给大家的全部内容了,我们下期再见! 💕 本文由沐风晓月原创,首发于CSDN博客, 博客主页:mufeng.blog.csdn.net 💕 日拱一卒无尽有,功不唐捐终入海 💕 喜欢的话记得点赞收藏哦



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3